using UnityEngine;
using System.Collections;
using OpenCvSharp;
using System.IO;
//using OpenCvSharp.CPlusPlus;
using System;
using System.Runtime.InteropServices;

[RequireComponent(typeof(Renderer))]
public class OpenCVFaceDetect : MonoBehaviour {
	
	public DeviceOrEmulator devOrEmu;
	private Kinect.KinectInterface kinect;
	private Texture2D tex;
	private CvMemStorage storage;
	private int depthImageWidth = 320;
	private int depthImageHeight = 240;
	private int perfCounter = 0;
	public float alpha = 0.25f;
	private bool jitterOff = true;
	private float jitterThres = 4.0f;
	private IplImage img,imgGray;
	byte[] test;
	Color32[] colorBuf;
	private CvHaarClassifierCascade face_Classifier;
	
	// Use this for initialization
	void Start () {
		kinect = devOrEmu.getKinect();
		tex = new Texture2D(640,480,TextureFormat.ARGB32,false);
		renderer.material.mainTexture = tex;
		storage = new CvMemStorage(0);
		test = new byte[depthImageWidth*depthImageHeight*3];
		img = Cv.CreateImage(Cv.Size(depthImageWidth,depthImageHeight), BitDepth.U8 , 3);
		imgGray = new IplImage(img.Size,BitDepth.U8,1);
		face_Classifier = CvHaarClassifierCascade.FromFile("haarcascade_frontalface_default.xml");
	}
	
	// Update is called once per frame
	void Update () {
		
//		if(perfCounter == 5)
//		{
//			perfCounter = 0;
//			tex.SetPixels32(colorBuf);
//			tex.Apply(false);
//			return;
//		}
//		perfCounter++;
		
		if (kinect.pollColor() )
		{
			
			colorBuf = kinect.getColor();
	
			Color32[] colorImage  = mipmapImg(colorBuf,640,480);
			for(int i = 0; i < 240; i++)
			{
				for(int j = 0; j < 320; j++)
				{
					int mipmapIdx = i*320+j;
					
					test[mipmapIdx*3] = colorImage[mipmapIdx].r;
					
					test[mipmapIdx*3+1] = colorImage[mipmapIdx].g;
					
					test[mipmapIdx*3+2]  = colorImage[mipmapIdx].b;	
				}				
			}		
			Marshal.Copy(test, 0, img.ImageData, depthImageWidth*depthImageHeight*3);
			Cv.CvtColor(img,imgGray,ColorConversion.RgbToGray);
			imgGray.Flip();
			CvSeq<CvAvgComp> faces = Cv.HaarDetectObjects(imgGray,face_Classifier,storage,1.5,1,HaarDetectionType.DoCannyPruning);
			for(int i =0;i<faces.Total;++i)
			{
				imgGray.Rectangle(faces[i].Value.Rect,CvColor.Red);	
			}
			imgGray.SaveImage("Assets/Resources/saveImage.png");			
			Debug.Log("Number of faces: "+ faces.Total);
			Marshal.Copy(imgGray.ImageData,test, 0,depthImageWidth*depthImageHeight*3);
			
			for(int i = 0; i < 240; i++)
			{
				for(int j = 0; j < 320; j++)
				{
					
					int mipmapIdx = (i*320+j);
					colorImage[mipmapIdx].r = test[mipmapIdx*3];
					colorImage[mipmapIdx].g = test[mipmapIdx*3+1];
					colorImage[mipmapIdx].b = test[mipmapIdx*3+2];
					
				}				
			}
			tex.SetPixels32(colorImage);
			tex.Apply(false);
		}
	}
	
	
	private Color32[] mipmapImg(Color32[] src, int width, int height)
	{
		int newWidth = width / 2;
		int newHeight = height / 2;
		Color32[] dst = new Color32[newWidth * newHeight];
		for(int yy = 0; yy < newHeight; yy++)
		{
			for(int xx = 0; xx < newWidth; xx++)
			{
				int TLidx = (xx * 2) + yy * 2 * width;
				int TRidx = (xx * 2 + 1) + yy * width * 2;
				int BLidx = (xx * 2) + (yy * 2 + 1) * width;
				int BRidx = (xx * 2 + 1) + (yy * 2 + 1) * width;
				dst[xx + yy * newWidth] = Color32.Lerp(Color32.Lerp(src[BLidx],src[BRidx],.5F),
				                                       Color32.Lerp(src[TLidx],src[TRidx],.5F),.5F);
			}
		}
		return dst;
	}
	void OnApplicationQuit()
	{
		Cv.ReleaseImage(img);
		Cv.ReleaseImage(imgGray);
	}
}
